#!/usr/bin/env python
# -*- coding: utf-8 -*-

# @Author  : 张亦辰
# @Copyright (c) Copyright 2025 张亦辰，All rights reserved。
# @File    : main.py
# @Software: PyCharm
# @Time    : 2025/10/4 21:47

"""
程序说明:
AI猜数字游戏规则：
1. 程序随机生成一个4位数整数，这4位数由1-9组成，且各位不重复。
2. AI需要根据程序提示，输入一个4位数整数，这4位数由1-9组成，且各位不重复。
3. 程序会根据AI输入的数字，提示玩家猜对了几个数字，以及猜对了几个数字的位置。
4. AI需要根据提示继续输入，用最少的次数猜对数字为止。
"""

import random
from GuessBase import GuessNumberGame


class AIGuessNumberGame(GuessNumberGame):
    """
    AI猜数字游戏类
    继承自基础猜数字游戏类，实现AI智能猜测逻辑
    """
    # 游戏模式, 0为玩家猜, 1为AI猜, 2为电脑出题AI猜，默认0
    game_mode: int = 0

    def __init__(self):
        """初始化AI游戏"""
        super().__init__()
        # AI的猜测历史
        self.guess_history = []


    def _generate_all_possible_numbers(self):
        """生成所有可能的4位数组合（1-9，不重复）"""
        from itertools import permutations
        stat = 0 if self.contain_zero == "0" else 1
        digits = [str(i) for i in range(stat, 10)]  # 0-9的数字
        # 生成所有4位数的排列组合
        all_combinations = [''.join(p) for p in permutations(digits, 4)]
        return all_combinations

    def _filter_possible_numbers(self, guess, result):
        """
        根据猜测结果过滤可能的数字
        guess: AI猜测的数字
        result: 比较结果（如"1全2中"）
        """
        filtered_numbers = []

        for number in self.possible_numbers:
            # 计算当前数字与猜测数字的比较结果
            correct_digits = 0  # 全的数量
            wrong_position_digits = 0  # 中的数量

            # 检查数字和位置都相同的情况
            for i in range(4):
                if guess[i] == number[i]:
                    correct_digits += 1

            # 检查数字相同但位置不同的情况
            for digit in guess:
                if digit in number and guess.index(digit) != number.index(digit):
                    wrong_position_digits += 1

            # 根据结果字符串解析期望的全和中数量
            if result == "0":
                expected_correct = 0
                expected_wrong_pos = 0
            else:
                # 解析结果字符串，如"1全2中"
                parts = result.split('全')
                if len(parts) > 1:
                    expected_correct = int(parts[0]) if parts[0] else 0
                    remaining = parts[1].split('中')
                    expected_wrong_pos = int(remaining[0]) if remaining[0] else 0
                else:
                    # 只有"中"的情况
                    parts = result.split('中')
                    expected_correct = 0
                    expected_wrong_pos = int(parts[0]) if parts[0] else 0

            # 如果匹配结果，则保留该数字
            if correct_digits == expected_correct and wrong_position_digits == expected_wrong_pos:
                filtered_numbers.append(number)

        return filtered_numbers

    def _make_smart_guess(self):
        """AI进行智能猜测"""
        if not self.possible_numbers:
            return None

        # 如果可能数字数量较少，直接返回第一个
        if len(self.possible_numbers) <= 10:
            return self.possible_numbers[0]

        # 使用最小最大算法：选择能最大程度减少可能性的数字
        best_guess = None
        min_max_remaining = float('inf')

        # 从可能数字中随机选择一部分进行优化（提高效率）
        sample_size = min(50, len(self.possible_numbers))
        candidates = random.sample(self.possible_numbers, sample_size)

        for candidate in candidates:
            # 计算该候选猜测的最坏情况下的剩余可能性
            max_remaining = 0

            # 考虑所有可能的结果
            for correct in range(5):  # 0-4个全
                for wrong_pos in range(5 - correct):  # 0-(4-correct)个中
                    if correct == 4:  # 猜对了，游戏结束
                        remaining = 1
                    else:
                        # 模拟该结果下的过滤
                        result_str = ""
                        if correct > 0:
                            result_str += f"{correct}全"
                        if wrong_pos > 0:
                            result_str += f"{wrong_pos}中"
                        if not result_str:
                            result_str = "0"

                        remaining = len(self._filter_possible_numbers(candidate, result_str))

                    max_remaining = max(max_remaining, remaining)

            if max_remaining < min_max_remaining:
                min_max_remaining = max_remaining
                best_guess = candidate

        return best_guess if best_guess else self.possible_numbers[0]

    def start_ai_game(self):
        """开始AI游戏"""
        print("AI猜数字游戏开始！")
        zero = input("请确认是否包含0（0包含，1或不输入不包含）: ")
        if zero == "0":
            self.set_contain_zero("0")
        else:
            self.set_contain_zero("1")

        # 所有可能的4位数组合（1-9，不重复）
        self.possible_numbers = self._generate_all_possible_numbers()
        if self.game_mode == 2:
            print(f"目标数字是：{self.target_number}")
        print("AI正在思考...")

        while True:
            # AI进行猜测
            ai_guess = self._make_smart_guess()
            if not ai_guess:
                print("AI无法找到有效猜测！")
                break

            print(f"AI猜测：{ai_guess}")

            # 验证AI猜测（应该总是有效的）
            is_valid, message = self._validate_input(ai_guess)
            if not is_valid:
                print(f"AI猜测无效：{message}")
                break

            # 比较数字
            is_correct = False
            result = ""
            if self.game_mode == 2:
                is_correct, result = self.compare_numbers(ai_guess)
            else:
                result =  input("请输入AI猜测的结果（正确为'4全'，错误为'0'或'1全2中'等）: ")
            print(f"结果：{result}")

            # 记录猜测历史
            self.guess_history.append((ai_guess, result))

            # 如果猜对了，结束游戏
            if is_correct == True or result == "4全":
                print(f"AI猜对了！总共用了{self.guesses}次猜测。")
                self._print_guess_history()
                break

            # 根据结果过滤可能的数字
            self.possible_numbers = self._filter_possible_numbers(ai_guess, result)
            print(f"剩余可能数字数量：{len(self.possible_numbers)}")

            if not self.possible_numbers:
                print("没有可能的数字了！")
                break

    def _print_guess_history(self):
        """打印AI的猜测历史"""
        print("\nAI猜测历史：")
        for i, (guess, result) in enumerate(self.guess_history, 1):
            print(f"第{i}次猜测：{guess} -> {result}")

    def start_game(self):
        """重写基础游戏方法，改为AI游戏"""
        module = (input("请选择游戏模式（0为玩家猜, 1为AI猜, 2为电脑出题AI猜）: ")).strip()
        if module == "0":
            self.game_mode = 0
        elif module == "1":
            self.game_mode = 1
        elif module == "2":
            self.game_mode = 2
        else:
            self.game_mode = 0

        if self.game_mode == 0:
            super().start_game()
        else:
            self.start_ai_game()

